﻿package systems.particles
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	
	/**
	 * ...
	 * @author nicoptere
	 */
	public class Clifford extends Sprite 
	{
		
		private var tmp:BitmapData;
		private var bd:BitmapData;
		private var p:Number;
		private var scale:Number = 100;
		
		private var _a:Number, _b:Number, _c:Number, _d:Number;
		private var la:Number, lb:Number, lc:Number, ld:Number;
		private var a:Number, b:Number, c:Number, d:Number;

		public function Clifford():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			tmp = new BitmapData( 600, 500, true ,0x00000000)
			bd = new BitmapData( 600, 500, true ,0x00000000 )
			addChild( new Bitmap( bd ));
			
			_a = la = 0.0;
			_b = lb = 0.0;
			_c = lc = 0.0;
			_d = ld = 0.0;
			
			/*			
			declare a=Interpolate(1.6,1.3);
			declare b=Interpolate(-0.6,1.7);
			declare c=Interpolate(-1.2,0.5);
			declare d=Interpolate(1.6,1.4);
			*/
			stage.addEventListener( MouseEvent.MOUSE_DOWN, reset );
			addEventListener( Event.ENTER_FRAME, update );
		}
		private function reset( e:Event ):void
		{
			_c = -Math.random() * 2.0;
			lc = Math.random() * 2.0;
			_d = Math.random() * 2.0;
			ld = Math.random() * 2.0;
		}
		private function update( e:Event ):void
		{
			
			_a = ( stage.stageWidth / 2 - mouseX ) / scale;
			//_b = ( stage.stageHeight / 2 - mouseY ) / scale;
			_b += 0.01;
			
			var lim:Number = 2;
			
			if ( _a < -lim ) _a = -lim;
			if ( _a > lim ) _a = lim;
			
			if ( _b < -lim ) _b = -lim;
			if ( _b > lim ) _b = -lim;
			/**/
			
			if ( _a == la && _b == lb ) return;
			
			tmp.fillRect( bd.rect, 0xFF000000 );
			p =	 0;
			var i:int = 0;
			var Z:Point = new Point( 0,0 ); 
			while ( p <= 1 )
			{
				
				
				a = Interpolate(_a, -_a );
				
				b = Interpolate(_b, -_a );
				
				c = Interpolate( _c, lc);
				
				d = Interpolate(_d, ld);
				
				i = 0;
				while (i < 100 ) 
				{
					
					Z.x = Math.sin(a * Z.y) + c * Math.cos(a * Z.x);
					Z.y = Math.sin(b * Z.x) + d * Math.cos(b * Z.y);
					tmp.setPixel32( 250 + Z.x * scale, 250 + Z.y * scale, 0xFFFFFFFF );
					i++;
				}
				p += 0.005;				
			}
			
			var ct:ColorTransform = new ColorTransform( 1, 1, 1, 1, 0, 0, 0, -128 );
			bd.draw( tmp, null, ct );
			la = _a;
			lb = _b;
			
		}
		private function Interpolate(x1:Number, x2:Number):Number
		{
			return 2 * Math.cos( Math.acos( x1 / 2) + p * (Math.acos(x2 / 2) - Math.acos(x1 / 2)));
		}
	}
}
